
#ifndef _K_GLOBAL_FUNCTIONS_H_
#define _K_GLOBAL_FUNCTIONS_H_



///////////////////////////////////////////////////////
// Usful Macro
///////////////////////////////////////////////////////

#ifndef arrsize
#define arrsize(a)  (sizeof(a)/sizeof(a[0]))
#endif

#ifndef	_DECL_K_HANDLE_MACRO_
#define _DECL_K_HANDLE_MACRO_

#define	DECLARE_FILE_HANDLE(name)	typedef uint32 name
#define DECLARE_CONTEXT(name)		typedef uint32 name
#define DECLARE_KHANDLE(name)		typedef uint32 name

#endif //_DECL_K_HANDLE_MACRO_

//------------------------------------------------------------------------------
// float to int conversion	
//------------------------------------------------------------------------------
inline int32 float_to_int(float f);
inline int32 double_to_int(double f);

//------------------------------------------------------------------------------
// sizes
//------------------------------------------------------------------------------
inline size_t gigabyte();
inline size_t megabyte();
inline size_t kilobyte();

//------------------------------------------------------------------------------
// 8bit,16bit,32bit int conversion	
//------------------------------------------------------------------------------

// make smaller values into a larger type
inline uint16	makeUint16(uint8 lo, uint8 hi);
inline uint32	makeUint32(uint16 lo, uint16 hi);
inline uint64	makeUint64(uint32 lo, uint32 hi);

// explicit hi/low part
inline uint32	loUint32(uint64 u64);
inline int32	loInt32(uint64 u64);

inline uint32	hiUint32(uint64 u64);
inline int32	hiInt32(uint64 u64);

inline uint16	loUint16(uint32 u32);
inline int16	loInt16(uint32 u32);

inline uint16	hiUint16(uint32 u32);
inline int16	hiInt16(uint32 u32);

inline uint8	loUint8(uint16 u16);
inline int8	loInt8(uint16 u16);

inline uint8	hiUint8(uint16 u16);
inline int8	hiInt8(uint16 u16);

// alternative explicit hi/low part
inline uint32	hiDword(uint64 v);
inline uint32	loDword(uint64 v);

inline uint16	hiWord(uint32 v);
inline uint16	loWord(uint32 v);

inline uint8	hiByte(uint16 v);
inline uint8	loByte(uint16 v);
		
// explicit hi/low swapping
inline uint16	swapUint16(uint16 v);
inline uint32	swapUint32(uint32 v);
inline uint64	swapUint64(uint64 v);

// explicit byte reversal
inline uint16	reverseUint16(uint16 v);
inline uint32	reverseUint32(uint32 v);

//------------------------------------------------------------------------------
//
//			MIN AND MAX STYLE FUNCTIONS
//
//------------------------------------------------------------------------------

#undef min
#undef max

//------------------------------------------------------------------------------
//	min()
//		Return minimum of 2 values
//------------------------------------------------------------------------------
template <typename T> inline
const T& min( const T& t1, const T& t2 );

//------------------------------------------------------------------------------
//	max()
//		Return maximum of 2 values
//------------------------------------------------------------------------------
template <typename T> inline
const T& max( const T& t1, const T& t2 );

//------------------------------------------------------------------------------
//	min()
//		Return minimum of 3 values
//------------------------------------------------------------------------------
template <typename T> inline
const T& min3( const T& t1, const T& t2, const T& t3 );

//------------------------------------------------------------------------------
//	max()
//		Return maximum of 3 values
//------------------------------------------------------------------------------
template <typename T> inline
const T& max3( const T& t1, const T& t2, const T& t3 );

//------------------------------------------------------------------------------
//	clamp()
//		Returns value clamped within [min,max]
//------------------------------------------------------------------------------
template <typename T> inline
const T& clamp( const T& minVal, const T& val, const T& maxVal );

//------------------------------------------------------------------------------
//	hiClamp()
//		Returns value clamped to a maximum val
//------------------------------------------------------------------------------
template <typename T> inline
const T& hiClamp( const T& val, const T& maxVal );

//------------------------------------------------------------------------------
//	loClamp()	
//		Returns value clamped to a minumum val
//------------------------------------------------------------------------------
template <typename T> inline
const T& loClamp( const T& minVal, const T& val );

//------------------------------------------------------------------------------
//	clampToUnit()	
//		Returns value clamped to [0,1]
//------------------------------------------------------------------------------
template <typename T> inline
const T clampToUnit(const T& v);

//------------------------------------------------------------------------------
//	clampToUint8()	
//		Clamps value to [0,255] integer
//------------------------------------------------------------------------------
template <typename T> inline
int clampToUint8(const T& v);

//------------------------------------------------------------------------------
//	clampToUint16()	
//		Clamps value to [0,65536] integer
//------------------------------------------------------------------------------
template <typename T> inline
int clampToUint16(const T& v);

//#ifndef _MSC_VER

//------------------------------------------------------------------------------
//	swap()
//		Swaps two values
//------------------------------------------------------------------------------
template <typename T> inline void swap(T& a, T& b);

//#endif // #ifndef _MSC_VER


//------------------------------------------------------------------------------
//	Sized type conversions to little endian and big endian. 
//	Where lsb means "least significant byte", 
//	and msb means "most significant byte".
//
//	#define BIG_ENDIAN if the target processor is big endian
//------------------------------------------------------------------------------

#ifdef BIG_ENDIAN

// motorola
inline uint16 uint16ToLsb(uint16 v);
inline uint32 uint32ToLsb(uint32 v);
inline uint16 uint16ToMsb(uint16 v);
inline uint32 uint32ToMsb(uint32 v);

enum { bigEndian=1, littleEndian=0 };

#else

// intel
inline uint16 uint16ToLsb(uint16 v);
inline uint32 uint32ToLsb(uint32 v);
inline uint16 uint16ToMsb(uint16 v);
inline uint32 uint32ToMsb(uint32 v);

enum { bigEndian=0, littleEndian=1 };

#endif // #ifdef BIG_ENDIAN


////////////////////////////////////////////////////////////////////////////////
// Inline Function Defined
////////////////////////////////////////////////////////////////////////////////

//------------------------------------------------------------------------------
// sizes
//------------------------------------------------------------------------------
inline size_t gigabyte()	{ return 1<<30; }
inline size_t megabyte()	{ return 1<<20; }
inline size_t kilobyte()	{ return 1<<10; }

//------------------------------------------------------------------------------
// 8bit,16bit,32bit int conversion
//------------------------------------------------------------------------------

// make smaller values into a larger type
inline uint16	makeUint16(uint8 lo, uint8 hi)		{ return uint16(uint16(lo) | (uint16(hi) << 8)); }
inline uint32	makeUint32(uint16 lo, uint16 hi)	{ return uint32(lo) | (uint32(hi) << 16); }
inline uint64	makeUint64(uint32 lo, uint32 hi)	{ return uint64(lo) | (uint64(hi) << 32); }

// explicit hi/low part
inline uint32	loUint32(uint64 u64)				{ return uint32(u64);		}
inline int32	loInt32(uint64 u64)					{ return int32(u64);		}

inline uint32	hiUint32(uint64 u64)				{ return uint32(u64 >> 32);	}
inline int32	hiInt32(uint64 u64)					{ return int32(u64 >> 32);	}

inline uint16	loUint16(uint32 u32)				{ return uint16(u32);		}
inline int16	loInt16(uint32 u32)					{ return int16(u32);		}

inline uint16	hiUint16(uint32 u32)				{ return uint16(u32 >> 16);	}
inline int16	hiInt16(uint32 u32)					{ return int16(u32 >> 16);	}

inline uint8	loUint8(uint16 u16)					{ return uint8(u16);		}
inline int8		loInt8(uint16 u16)					{ return int8(u16);			}

inline uint8	hiUint8(uint16 u16)					{ return uint8(u16 >> 8);	}
inline int8		hiInt8(uint16 u16)					{ return int8(u16 >> 8);	}

// alternative explicit hi/low part
inline uint32	hiDword(uint64 v)					{ return hiUint32(v);		}
inline uint32	loDword(uint64 v)					{ return loUint32(v);		}

inline uint16	hiWord(uint32 v)					{ return hiUint16(v);		}
inline uint16	loWord(uint32 v)					{ return loUint16(v);		}

inline uint8	hiByte(uint16 v)					{ return hiUint8(v);		}
inline uint8	loByte(uint16 v)					{ return loUint8(v);		}
		
// explicit hi/low swapping
inline uint16	swapUint16(uint16 v)				{ return (uint16)((v<<8) | (v>>8));	}
inline uint32	swapUint32(uint32 v)				{ return (v<<16) | (v>>16);	}
inline uint64	swapUint64(uint64 v)				{ return (v<<32) | (v>>32);	}

// explicit byte reversal
inline uint16	reverseUint16(uint16 v)				{ return (uint16)((v<<8) | (v>>8));	}

inline uint32	reverseUint32(uint32 v)				{ return ((v>>24) |
															  ((v&0x00FF0000)>>8) |
															  ((v&0x0000FF00)<<8) |
															  (v<<24) ); }

//-----------------------------------------------------------------------------
//  conversion functions
//-----------------------------------------------------------------------------
inline int32 float_to_int(float f)
{
#ifdef __BORLANDC__
	return int32(f);
#else
	uint16	control_word_1;
	uint16	control_word_2;
	int32	res;
	__asm
	{
		fld f

		wait
		fnstcw	control_word_1
		wait

		mov		ax,control_word_1
		or		ah,0xC
		mov		word ptr control_word_2,ax
		fldcw	control_word_2
		fistp	res
		fldcw	control_word_1
	}
	return res;
#endif
}

inline int32 double_to_int(double f)
{
#ifdef __BORLANDC__
	return int32(f);
#else
	uint16	control_word_1;
	uint16	control_word_2;
	int32	res;
	__asm
	{
		fld		qword ptr [f]

		fnstcw	control_word_1

		mov		ax,control_word_1
		or		ah,0xC
		mov		word ptr control_word_2,ax
		fldcw	control_word_2
		fistp	res
		fldcw	control_word_1
	}
	return res;
#endif
}



//------------------------------------------------------------------------------
//
//			MIN AND MAX STYLE FUNCTIONS
//
//------------------------------------------------------------------------------

#undef min
#undef max

//------------------------------------------------------------------------------
//	min()
//		Return minimum of 2 values
//------------------------------------------------------------------------------
template <typename T> 
inline const T& min( const T& t1, const T& t2 )
{ return t1>t2 ? t2 : t1; }

//------------------------------------------------------------------------------
//	max()
//		Return maximum of 2 values
//------------------------------------------------------------------------------
template <typename T> 
inline const T& max( const T& t1, const T& t2 )
{ return t1>t2 ? t1 : t2; }

//------------------------------------------------------------------------------
//	min()
//		Return minimum of 3 values
//------------------------------------------------------------------------------
template <typename T> 
inline const T& min3( const T& t1, const T& t2, const T& t3 )
{ return t1>t2 ? (t2>t3 ? t3 : t2) : (t1>t3 ? t3 : t1 ); }

//------------------------------------------------------------------------------
//	max()
//		Return maximum of 3 values
//------------------------------------------------------------------------------
template <typename T> 
inline const T& max3( const T& t1, const T& t2, const T& t3 )
{ return t1>t2 ? (t1>t3 ? t1 : t3) : (t2>t3 ? t2 : t3 ); }

//------------------------------------------------------------------------------
//	clamp()
//		Returns value clamped within [min,max]
//------------------------------------------------------------------------------
template <typename T> 
inline const T& clamp( const T& minVal, const T& val, const T& maxVal )	
{ return std::max( minVal, min( maxVal, val ) ); }

//------------------------------------------------------------------------------
//	hiClamp()
//		Returns value clamped to a maximum val
//------------------------------------------------------------------------------
template <typename T> inline 
const T& hiClamp( const T& val, const T& maxVal )	
{ return std::min( maxVal, val ); }

//------------------------------------------------------------------------------
//	loClamp()	
//		Returns value clamped to a minumum val
//------------------------------------------------------------------------------
template <typename T> 
inline const T& loClamp( const T& minVal, const T& val )	
{ return max( minVal, val ); }

//------------------------------------------------------------------------------
//	clampToUnit()	
//		Returns value clamped to [0,1]
//------------------------------------------------------------------------------
template <typename T> 
inline const T clampToUnit(const T& v) 
{ return clamp(T(0),v,T(1)); }

//------------------------------------------------------------------------------
//	clampToUint8()	
//		Clamps value to [0,255]
//------------------------------------------------------------------------------
template <typename T> 
inline int clampToUint8(const T& v) 
{ return clamp(int(0),(int)v,int(255)); }

//------------------------------------------------------------------------------
//	clampToUint16()	
//		Clamps value to [0,65536]
//------------------------------------------------------------------------------
template <typename T> 
inline int clampToUint16(const T& v) 
{ return clamp(int(0),(int)v,int(65536)); }

//#ifndef _MSC_VER

//------------------------------------------------------------------------------
//	swap()
//		Swaps two values
//------------------------------------------------------------------------------
template <typename T> 
inline void	swap(T& a, T& b)		
{ T temp = a; a = b; b = temp; }

//#endif // #ifndef _MSC_VER


//------------------------------------------------------------------------------
//	Sized type conversions to little endian and big endian. 
//	Where lsb means "least significant byte", 
//	and msb means "most significant byte".
//
//	#define BIG_ENDIAN if the target processor is big endian
//------------------------------------------------------------------------------

#ifdef BIG_ENDIAN

// motorola
inline uint16 uint16ToLsb(uint16 v)				{ return reverseUint16(v); }
inline uint32 uint32ToLsb(uint32 v)				{ return reverseUint32(v); }
inline uint16 uint16ToMsb(uint16 v)				{ return v; }
inline uint32 uint32ToMsb(uint32 v)				{ return v; }

#else

// intel
inline uint16 uint16ToLsb(uint16 v)				{ return v; }
inline uint32 uint32ToLsb(uint32 v)				{ return v; }
inline uint16 uint16ToMsb(uint16 v)				{ return reverseUint16(v); }
inline uint32 uint32ToMsb(uint32 v)				{ return reverseUint32(v); }

#endif //BIG_ENDIAN

#endif